package com.obas.view.script {
   import com.ease.util.StringUtils;
   import com.ease.framework.CommandCompletionEvent;
   import com.obas.component.tree.treeclass.Node;
   import com.obas.constants.TestingLibConstants;
   import com.obas.event.ScriptOperationEvent;
   import com.obas.flex.common.util.ResourceUtil;
   import com.obas.model.business.TestcaseScript;
   import com.obas.model.VerifyHelper;
   import com.obas.business.common.vo.AtMessage;
   import com.obas.view.menu.InspectMenu;
   import com.ease.component.managers.ConfirmHelper;
   import com.ease.component.managers.ErrorManager;
   import com.ease.component.managers.ProgressManager;
   import com.ease.component.util.FireFoxCmdSupport;

   import flash.events.EventDispatcher;
   import flash.events.MouseEvent;
   import flash.external.ExternalInterface;
   import flash.geom.Rectangle;
   import flash.text.TextField;
   import flash.text.TextLineMetrics;
   import flash.utils.Dictionary;

   import mx.collections.ArrayCollection;
   import mx.controls.Alert;
   import mx.core.IUITextField;
   import mx.core.mx_internal;
   import mx.events.DynamicEvent;
   import mx.events.ListEvent;
   import mx.managers.PopUpManager;
   import mx.utils.StringUtil;
   import mx.utils.URLUtil;

   [Event(name="{com.obas.event.ScriptOperationEvent.REQUEST_ID}", type="com.obas.event.ScriptOperationEvent")]
   public class ScriptEditViewMediator extends EventDispatcher {
      public static const LOADER_HTML:String = "agent/core/autloader.html";

      private var _pageId:String;
      private var _loaderURL:String;

      private var _verifying:Boolean = false;

      private var _nodeIdMap:Dictionary = new Dictionary();

      private var _stepIndex:int = 0;
      private var _stepOffset:int = 0;

      private var _view:ScriptEditView;

      [InjectableView]
      public function get view():ScriptEditView {
         return _view;
      }

      public function set view(value:ScriptEditView):void {
         _view = value;
         init();
      }

      private function init():void {
         view.startBtn.addEventListener(MouseEvent.CLICK, onStartAut);
         view.shutDownBtn.addEventListener(MouseEvent.CLICK, onShutDownAut);
         view.recordBtn.addEventListener(MouseEvent.CLICK, onRecord);
         view.playBtn.addEventListener(MouseEvent.CLICK, onPlay);
         view.saveBtn.addEventListener(MouseEvent.CLICK, onSave);
         view.feed.addEventListener("message", onMessageReceive);
         view.feed.addEventListener("fault", onMessageFault);
         view.objectTree.remoteServiceFunc = getTreeChildren;
         view.objectTree.addEventListener(ListEvent.CHANGE, onObjectTreeChange);
         view.objectTree.addEventListener(InspectMenu.INSPECT, onInspect);
         view.objectTree.addEventListener(InspectMenu.VIEW, onView);
         view.objectTree.addEventListener(InspectMenu.VERIFY, onVerify);
         view.feed.init();
         dispatchEvent(new ScriptOperationEvent([view.testScript.id], ScriptOperationEvent.FETCH_TEST_SCRIPT));
      }

      private function onStartAut(e:*):void {
         var fullLoaderURL:String = getFullLoaderURL();
         var datetime:Date = new Date();
         _pageId = "IE" + datetime.time;
         FireFoxCmdSupport.runCmd(
            "C:\\\\Windows\\\\system32\\\\mshta.exe",
            [fullLoaderURL + "?debug=true&autURL=" + view.endPoint.text + "&pageId=" + _pageId]);
         dispatchEvent(new ScriptOperationEvent([_pageId, view.testScript.id], ScriptOperationEvent.START_APP));
         view.feed.subscribe(_pageId);
         view.state = TestingLibConstants.IDE_STATE_CONNECTED;
      }

      private function onShutDownAut(e:*):void {
         view.state = TestingLibConstants.IDE_STATE_INIT;
         view.feed.unsubscribe();
         view.arrow.visible = false;
         view.treeDatas = null;
         dispatchEvent(new ScriptOperationEvent([_pageId], ScriptOperationEvent.STOP_APP));
      }

      private function onRecord(e:*):void {
         view.state = TestingLibConstants.IDE_STATE_RECORDING;
         dispatchEvent(new ScriptOperationEvent([_pageId]));
      }

      private function onPlay(e:*):void {
         view.state = TestingLibConstants.IDE_STATE_RUNNING;
         if (!view.arrow.visible) {
            view.arrow.visible = true;
         }
         _stepIndex = 0;
         _stepOffset = 0;
         if (view.scriptArea.verticalScrollPosition != 0) {
            view.lineNum.verticalScrollPosition = view.scriptArea.verticalScrollPosition = 0;
         }
         dispatchEvent(new ScriptOperationEvent([_pageId], ScriptOperationEvent.START_RUN));

      }

      private function onSave(e:*):void {
         view.testScript.script = view.scriptArea.text;
         dispatchEvent(new ScriptOperationEvent([view.testScript.id, view.testScript.script], ScriptOperationEvent.SAVE_TEST_SCRIPT));
      }

      private function onObjectTreeChange(event:*):void {
         _verifying = false;
         var node:Node = view.objectTree.selectedItem as Node;
         getObjectProperties(node);
      }

      private function onInspect(e:*):void {
         var node:Node = view.objectTree.selectedItem as Node;
         var param:Object = new Object();
         param.enable = true;
         var msg:AtMessage = new AtMessage();
         msg.command = TestingLibConstants.TOGGLE_INSPECT_MODE;
         msg.param = param;
         msg.id = genMsgId();
         dispatchEvent(new ScriptOperationEvent([_pageId, msg], ScriptOperationEvent.TOGGLE_INSPECT_MODE));
      }

      private function onView(e:*):void {
         var node:Node = view.objectTree.selectedItem as Node;
         viewObject(node);
      }

      private function onVerify(e:*):void {
         _verifying = true;
         var node:Node = view.objectTree.selectedItem as Node;
         getObjectProperties(node);
      }

      private function onMessageReceive(event:*):void {
         var msg:AtMessage = event.spec;
         var param:* = msg.param;
         switch (msg.command) {
            case TestingLibConstants.AGENT_CONNECTED:
               dispatchEvent(new ScriptOperationEvent([_pageId], ScriptOperationEvent.GET_TREE_ROOT));
               break
            case TestingLibConstants.EVENT_RECORDED:
            case TestingLibConstants.VERIFICATION:
               var str:String = param.recordingText;
               if (StringUtils.isNullorEmpty(view.scriptText)) {
                  view.scriptText = str;
               }
               else if (StringUtils.endsWith(view.scriptText, view.crlf)) {
                  view.scriptText += str;
               }
               else {
                  view.scriptText += view.crlf + str;
               }
               break;
            case TestingLibConstants.IDE_STEPPINGOVER:
               exeStepOver(msg);
               break;
            case TestingLibConstants.STOP_RUN:
               exeStopRun(msg);
               break;
            case TestingLibConstants.ERROR:
               exeError(msg);
               break;
            case TestingLibConstants.OBJECT_HOVER:
               var locator:Array = param.locator;
               prepareObjTree(locator);
               break;
            case TestingLibConstants.GET_PROPERTIES:
               ProgressManager.hideProgress(view);
               if (_verifying) {
                  var verifyDialog:VerifyWindow = PopUpManager.createPopUp(view.root, VerifyWindow, true) as VerifyWindow;
                  verifyDialog.properties = new ArrayCollection(param.propertyData);
                  verifyDialog.callBack = onVerifyBack;
                  PopUpManager.centerPopUp(verifyDialog);
               }
               else {
                  view.adg.dataProvider = new ArrayCollection(param.propertyData);
               }
               break;
            case TestingLibConstants.GET_TREE_ROOT:
               var rootNode:Node = view.objectTree.nodeFactory.createNode(getNodeModel(param.rootData));
               rootNode.type = TestingLibConstants.ITEMTYPE_OBJECT;
               view.objectTree.rootNode = rootNode;
               view.treeDatas = new ArrayCollection([rootNode]);
               break;
            case TestingLibConstants.GET_TREE_CHILDREN:
               if (_nodeIdMap[msg.id]) {
                  var parentNode:Node = _nodeIdMap[msg.id];
                  delete _nodeIdMap[msg.id];
                  view.objectTree.appendChildren(new ArrayCollection(param.childrenData), parentNode);
               }
               break;
            default:
               break;
         }
      }

      private function exeStopRun(msg:AtMessage):void {
         view.arrow.visible = false;
         ConfirmHelper.showInformationDialog("", "脚本执行成功。");
      }

      private function exeStepOver(msg:AtMessage):void {
         var param:* = msg.param;
         var script:String = param.script;
         var lines:Array = view.scriptArea.text.split(view.crlf);
         _stepIndex = lines.indexOf(script, _stepIndex);
         var field:IUITextField = view.scriptArea.mx_internal::getTextField();
         var lineMe:TextLineMetrics = field.getLineMetrics(0);
         var lineHeight:Number = lineMe.height;
         var rect:Rectangle = field.getBounds(view.scriptArea);
         if ((_stepIndex - _stepOffset) * lineHeight > rect.height - rect.y) {
             view.lineNum.verticalScrollPosition = view.scriptArea.verticalScrollPosition = _stepIndex ;
             _stepOffset = view.scriptArea.verticalScrollPosition;
         }
         view.arrow.move(0, (_stepIndex - _stepOffset) * lineHeight + 34);
      }

      private function exeError(msg:AtMessage):void {
         var param:Object = msg.param;
         if (param.hasOwnProperty("msg")) {
            ConfirmHelper.showInformationDialog("失败", param.msg);
         }
         else {
            ConfirmHelper.showInformationDialog("失败", "验证对象属性失败");
         }
      }

      private function onVerifyBack(item:VerifyHelper):void {
         var entity:* = view.objectTree.selectedItem.entity;
         var verifyStr:String = "";
         if (item.opType == 0) {
            verifyStr += "verifyEqual(";
         }
         else {
            //TODO:....
         }
         var locatorPart:* = entity.locatorPart;
         verifyStr += locatorPart.automationClassName + "(" + locatorPart.automationName + ")";
         verifyStr += "." +item.propertyName;
         verifyStr += ", ";
         verifyStr += item.valueCode;//TODO:.....
         verifyStr += ")";
         view.scriptText += verifyStr;
      }

      [ResponseHandler("{com.obas.event.ScriptOperationEvent.RETURN_ID}")]
      public function onScriptOperationEvent(event:CommandCompletionEvent):void {
         if (event.error) {
            ErrorManager.showErrorMessage(ResourceUtil.getErrorString("", event.error));
            return ;
         }
         var request:ScriptOperationEvent = event.request as ScriptOperationEvent;
         if (request.actionType == ScriptOperationEvent.SAVE_TEST_SCRIPT) {
            view.testScript = event.result as TestcaseScript;
            ConfirmHelper.showInformationDialog("", "保存脚本成功");
         }
         else if (request.actionType == ScriptOperationEvent.FETCH_TEST_SCRIPT) {
            view.testScript = event.result as TestcaseScript;
         }
      }

      private function viewObject(node:Node):void {
         var param:Object = new Object();
         param.parts = getNodeLocator(node);
         param.show = true;
         var msg:AtMessage = new AtMessage();
         msg.id = genMsgId();
         msg.command = TestingLibConstants.TOGGLE_INSPECT_FRAME;
         msg.param = param;
         dispatchEvent(new ScriptOperationEvent([_pageId, msg], ScriptOperationEvent.TOGGLE_INSPECT_FRAME));
      }

      private function getObjectProperties(node:Node):void {
         ProgressManager.showProgress(view, ProgressManager.LOADING_SPINNER);
         var param:Object = new Object();
         param.parts = getNodeLocator(node);
         param.extraProps = false;
         var msg:AtMessage = new AtMessage();
         msg.id = genMsgId();
         msg.command = TestingLibConstants.GET_PROPERTIES;
         msg.param = param;
         dispatchEvent(new ScriptOperationEvent([_pageId, msg], ScriptOperationEvent.GET_PROPERTIES));
      }

      private function getNodeModel(entity:*):* {
         var locatorPart:* = entity.locatorPart;
         entity.name = locatorPart.automationClassName + "(" + locatorPart.automationName + ")";
         return entity;
      }

      private function getTreeChildren(node:Node):void {
         var params:Object = new Object();
         params.parts = getNodeLocator(node);
         var msg:AtMessage = new AtMessage();
         msg.id = genMsgId();
         msg.command = TestingLibConstants.GET_TREE_CHILDREN;
         msg.param = params;
         _nodeIdMap[msg.id] = node;
         dispatchEvent(new ScriptOperationEvent([_pageId, msg], ScriptOperationEvent.GET_TREE_CHILDREN));
      }

      private function prepareObjTree(locator:Array):void {
         var parentNode:Node = view.objectTree.rootNode;
         for (var ii:int = 0; ii < locator.length; ii++) {
            var child:* = locator[ii];
            if (!parentNode || !child.children) {
               continue;
            }
            if (!parentNode.initialized) {
               view.objectTree.appendChildren(new ArrayCollection(child.children), parentNode);
            }
            parentNode = parentNode.children.getItemAt(child.childIndex) as Node;
            if (ii == locator.length - 1) {
               view.objectTree.selectedItem = parentNode;
               viewObject(parentNode);
            }
         }
      }

      private function onMessageFault(event:DynamicEvent):void {
         ErrorManager.showErrorMessage(event.faultString, event.faultDetail);
      }

      private function getNodeLocator(node:Node):Array {
         var parts:Array = [];
         while (node) {
            parts.unshift(node.entity.locatorPart);
            node = node.parentNode;
         }

         return parts;
      }

      private function getFullLoaderURL():String {
         if (!_loaderURL) {
            var contextPath:String = ExternalInterface.call("BrowserHistory.getURL");
            if (URLUtil.isHttpURL(contextPath)) {
               _loaderURL = URLUtil.getFullURL(contextPath, LOADER_HTML)
            } else {
               _loaderURL = "/" + contextPath + "/" + LOADER_HTML;
            }
         }

         return _loaderURL;
      }

      private var curMsgId:int = 2;
      private function genMsgId():int {
         if (curMsgId < int.MAX_VALUE - 2) {
            curMsgId = curMsgId + 2;
         }
         else {
            curMsgId = 2;
         }
         return curMsgId;
      }
   }
}